package com.shanghaionstar.retrofit.http;


import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.common.util.DeviceUtil;
import com.onstar.cn.framework.network.ClientTraceInstance;
import com.onstar.cn.framework.utils.CertString;
import com.shanghaionstar.BuildConfig;
import com.shanghaionstar.remote.manager.VehicleService;
import com.shanghaionstar.utils.ApplicationUtil;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * Created by OnStar on 2017/6/27.
 */

public class RetrofitManager {

    private static volatile OkHttpClient sOkHttpClient;
    private static HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    public static final String[] CAPINPUTNAMES_PROD = {CertString.M_PRD, CertString.PORTAL_PRD, CertString.PRD};
    public static final String[] CAPINPUTNAMES_IDT1 = {CertString.PORTAL_TEST, CertString.TEST_CER};
    public static final String[] CAPINPUTNAMES_VV2 = {CertString.PORTAL_TEST, CertString.TEST_CER, CertString.VV2_API};

    static {
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        initOkHttpClient();
    }

//    public static UsersService getUserService() {
//        return createApi(UsersService.class, ApiConstants.API_BASE_URL);
//    }
//
//    public static VehicleService getVehicleService() {
//        return createApi(VehicleService.class, ApiConstants.API_BASE_URL);
//    }
//
    public static VehicleService getVehicleService() {
        return createApi(VehicleService.class, "https://api-idt1.shanghaionstar.com:1443");
    }

    @NonNull
    private static StringBuilder getStringBuilder() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("ANDROID");
        stringBuilder.append("_");
        stringBuilder.append(Build.VERSION.RELEASE);
        stringBuilder.append("_");
        stringBuilder.append(BuildConfig.VERSION_CODE);
        stringBuilder.append("_");
        if (DeviceUtil.getLanguage() != null && DeviceUtil.getCountry() != null) {
            stringBuilder.append(DeviceUtil.getLanguage() + "-" + DeviceUtil.getCountry().toUpperCase());
        } else {
            stringBuilder.append("zh-CN");
        }
        stringBuilder.append("_");
        stringBuilder.append(DeviceUtil.getDeviceType());
        stringBuilder.append("_");
        stringBuilder.append(Constants.CLIENT_INFO_SECRET_ID);
        return stringBuilder;
    }


    public static Map<String, String> getHeaders() {
        String clientTraceId = ClientTraceInstance.getInstance().getClientTraceId();
        StringBuilder stringBuilder = getStringBuilder();
        String token = ApplicationUtil.getInstance().getToken();
        String authorization = TextUtils.isEmpty(token) ? "Authorization" : token;
        Map<String, String> headers = new HashMap<>();
        headers.put("CLIENT-TRACE-ID", clientTraceId);
        headers.put("CLIENT-INFO", stringBuilder.toString());
        headers.put("Authorization", authorization);
        return headers;
    }

    /**
     * 根据传入的baseUrl，和api创建retrofit
     */
    private static <T> T createApi(Class<T> clazz, String baseUrl) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(sOkHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(clazz);
    }

    private static void initOkHttpClient() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        if (sOkHttpClient == null) {
            synchronized (RetrofitManager.class) {
                if (sOkHttpClient == null) {
                    OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
                    okHttpBuilder.connectTimeout(6, TimeUnit.SECONDS)
                            .readTimeout(15, TimeUnit.SECONDS)
                            .writeTimeout(15, TimeUnit.SECONDS)
                            .addNetworkInterceptor(new StethoInterceptor())
                            .addInterceptor(logging)
                            .addInterceptor(new Interceptor() {
                                @Override
                                public Response intercept(Chain chain) throws IOException {
                                    Request.Builder builder = chain.request().newBuilder();
                                    builder.addHeader("Content-Type", "application/json; charset=utf-8")
                                            .addHeader("Accept", "application/json")
//                                            .addHeader("auth","123")
                                            .addHeader("Accept-Language", "zh-CN");
                                    return chain.proceed(builder.build());
                                }
                            });
//                    if (com.shanghaionstar.BuildConfig.ISProdEnv) {
//                        okHttpBuilder.sslSocketFactory(getSSLContext(CAPINPUTNAMES_PROD).getSocketFactory());
//                    } else {
//                        okHttpBuilder.sslSocketFactory(getSSLContext(CAPINPUTNAMES_IDT1).getSocketFactory());
//                    }
                    sOkHttpClient = okHttpBuilder.build();
                }
            }
        }
    }


    /**
     * 初始化SSL 服务器认证
     *
     * @return
     */
    private static SSLContext getSSLContext(String[] capInputNames) {
        SSLContext sslcontext = null;
        InputStream[] caInputs = new InputStream[capInputNames.length];
        try {
            for (int i = 0; i < capInputNames.length; i++) {
                caInputs[i] = new ByteArrayInputStream(capInputNames[i].getBytes());
            }
            sslcontext = SSLContext.getInstance("TLSv1");
            sslcontext.init(null, prepareTrustManager(caInputs), null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sslcontext;
    }

    private static TrustManager[] prepareTrustManager(InputStream... certificates) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
        if (certificates == null || certificates.length <= 0) return null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            int index = 0;
            for (InputStream is : certificates) {
                String certificateAlias = Integer.toString(index++);
                Certificate certificate = certificateFactory.generateCertificate(is);
                keyStore.setCertificateEntry(certificateAlias, certificate);
                try {
                    if (is != null)
                        is.close();
                } catch (IOException ignored) {
                }
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            return trustManagerFactory.getTrustManagers();
            // TODO: 2016/11/11 针对有效期异常导致校验失败的情况，目前没有完美的解决方案
        } catch (CertificateException e1) {
            throw e1;
        } catch (NoSuchAlgorithmException e2) {
            throw e2;
        } catch (KeyStoreException e3) {
            throw e3;
        } catch (IOException e4) {
            throw e4;
        }
    }
}
